package com.gt.self.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gt.common.AjaxResult;
import com.gt.common.DateUtils;
import com.gt.common.PrintUtil;
import com.gt.common.SelfStatus;
import com.gt.self.domain.PrintInfoDao;
import com.gt.self.domain.UsPrintInfo;
import com.gt.self.domain.UsPrintTask;
import com.gt.self.domain.vo.PrintInfoVo;
import com.gt.self.domain.vo.ReportParamVo;
import com.gt.self.mapper.UsPrintInfoMapper;
import com.gt.self.service.SelfMachinePrintService;
import com.gt.self.service.UsCheckListService;
import com.gt.self.service.UsPrintInfoService;
import com.gt.self.service.UsPrintTaskService;
import com.gt.self.service.UsPrintTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * 自助报道打印服务
 */
@Slf4j
@Service
public class SelfMachinePrintServiceImpl implements SelfMachinePrintService {

    @Autowired
    private UsCheckListService usCheckListService;

    @Autowired
    private UsPrintInfoService usPrintInfoService;

    @Autowired
    private UsPrintTaskService usPrintTaskService;

    @Value("${print.PDFPath}")
    private String printPDFPath;

    @Value("${print.remoteUrl}")
    private String remoteUrl;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public AjaxResult selfServicePrint(String commonNo) throws ParseException {

        int statusFlag = 0;//状态标志
        List<String> printList = new ArrayList<>();
        List<PrintInfoDao> selfPrintDataList = usCheckListService.getSelfPrintData(commonNo);

        if (selfPrintDataList == null || selfPrintDataList.size() < 1) {
            log.error("没有打印报告单，请求数据：[{}]", commonNo);
            return AjaxResult.error(SelfStatus.NU_EXIT, "没有打印报告单！");
        }
        for (PrintInfoDao printInfoDao : selfPrintDataList) {
            String reportStatus = printInfoDao.getReportStatus();
            if (StringUtils.isBlank(reportStatus) || reportStatus.equals("1")) {
                log.info("报告检查中，请等待，请求数据：[{}]", commonNo);
                if (SelfStatus.SUCCESS == statusFlag) {
                    //只要有一条打印成功，就不用提示信息
                    continue;
                }
                statusFlag = SelfStatus.CHECK_STATUS;
                continue;
            }

            if (reportStatus.equals("3")) {
                log.info("报告已打印，报告数据：[{}]", commonNo);
                if (SelfStatus.SUCCESS == statusFlag) {
                    //只要有一条打印成功，就不用提示信息
                    continue;
                }
                statusFlag = SelfStatus.PRINT_FINISH;
                continue;
            }

            if (reportStatus.equals("2")) {
                Date checkTime = printInfoDao.getCheckTime();
                if (checkTime == null) {
                    log.info("检查时间或审核时间为空，请求数据：[{}]", commonNo);
                    if (SelfStatus.SUCCESS == statusFlag) {
                        //只要有一条打印成功，就不用提示信息
                        continue;
                    }
                    statusFlag = SelfStatus.ERROR;
                    continue;
                }
                long milliBetween = DateUtils.getMilliBetween(checkTime, new Date());
                if (milliBetween < 0.1) {
                    log.info("报告审核中，请等待，报告数据：[{}]", commonNo);
                    saveTaskData(printInfoDao);
                    if (SelfStatus.SUCCESS == statusFlag) {
                        //只要有一条打印成功，就不用提示信息
                        continue;
                    }
                    statusFlag = SelfStatus.AUDITED_STATUS;
                    continue;
                }
                //synPdf(printInfoDao.getCheckListId());
                printInfoDao.setPrintUrl(printPDFPath + printInfoDao.getCheckListId() + ".pdf");
                createPrintData(printInfoDao);
                printList.add(printInfoDao.getApplyNo());
//                PrintUtil.PrintPdfByPath(printInfoDao.getPrintUrl());
                statusFlag = SelfStatus.SUCCESS;
            }
        }

        switch (statusFlag) {
            case SelfStatus.SUCCESS:
                return AjaxResult.success().put("printList", printList);
            case SelfStatus.CHECK_STATUS:
                return AjaxResult.error(SelfStatus.CHECK_STATUS, "报告检查中，请等待！");
            case SelfStatus.PRINT_FINISH:
                return AjaxResult.error(SelfStatus.PRINT_FINISH, "报告已打印！");
            case SelfStatus.AUDITED_STATUS:
                AjaxResult error = AjaxResult.error(SelfStatus.AUDITED_STATUS, "报告审核中，请等待！");
                error.put("waitTime", "10");
                return error;
            default:
                return AjaxResult.error(SelfStatus.ERROR, "业务异常");
        }
    }

    /**
     * 同步远程pdf(这个方法后续需要独立出来同步pdf)
     *
     * @param checkList
     */
    private void synPdf(String checkList) {

        ResponseEntity<Resource> response = restTemplate.getForEntity(remoteUrl + checkList + ".pdf", Resource.class);
        if (response.getStatusCode() == HttpStatus.OK) {
            Resource resource = response.getBody();
            File file = new File(printPDFPath + checkList + ".pdf");
            try (InputStream inputStream = resource.getInputStream();
                 FileOutputStream fileOutputStream = new FileOutputStream(file)) {
                int byteRead;
                byte[] buffer = new byte[1024];
                while ((byteRead = inputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, byteRead);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


    @Override
    public List<PrintInfoVo> selectFinishPrintInfoByApplyNo(ReportParamVo reportParamVo) {
        List<PrintInfoVo> printInfoVoList = new ArrayList<>();
        PrintInfoVo printInfoVo = new PrintInfoVo();
        PrintInfoDao printData = usCheckListService.selectFinishPrintInfoByApplyNo(reportParamVo);
        if (printData == null) {
            return null;
        }
        BeanUtils.copyProperties(printData, printInfoVo);
        printInfoVoList.add(printInfoVo);
        return printInfoVoList;
    }

    @Override
    public List<PrintInfoVo> selectFinishPrintInfo(ReportParamVo reportParamVo) {
        List<PrintInfoVo> printInfoVoList = new ArrayList<>();
        PrintInfoVo printInfoVo = new PrintInfoVo();

        List<PrintInfoDao> printDataList = usCheckListService.selectFinishPrintInfo(reportParamVo);
        if (printDataList == null && printDataList.size() < 1) {
            return null;
        }
        for (PrintInfoDao printData : printDataList) {
            BeanUtils.copyProperties(printData, printInfoVo);
            printInfoVoList.add(printInfoVo);
        }
        return printInfoVoList;
    }


    /**
     * 保存定时任务谁
     * 在报告生成10分钟后才可以打印
     *
     * @param printData
     */
    private void saveTaskData(PrintInfoDao printData) {
        UsPrintTask usPrintTask = new UsPrintTask();
        BeanUtils.copyProperties(printData, usPrintTask);
        usPrintTask.setPrintStatus("审核中");

        /**报告时间延长十分钟**/
        Date checkTime = printData.getCheckTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(checkTime);
        calendar.add(Calendar.MINUTE, 2);
        Date taskDate = calendar.getTime();
        usPrintTask.setTaskTime(taskDate);

        usPrintTaskService.save(usPrintTask);
    }

    /**
     * 创建打印数据
     *
     * @param printData
     * @return
     */
    private void createPrintData(PrintInfoDao printData) {
        UsPrintInfo usPrintInfo = new UsPrintInfo();
        BeanUtils.copyProperties(printData, usPrintInfo);
        usPrintInfo.setPrintStatus("已打印");
        usPrintInfoService.save(usPrintInfo);
        usCheckListService.updatePrintStatus(printData);
    }


    @Override
    public AjaxResult selfServicePrint1(ReportParamVo reportParamVo) {


        return null;
    }

    @Override
    public AjaxResult print(List<String> applyNOs) {
        if (applyNOs == null || applyNOs.size() < 1) {
            return AjaxResult.error("打印失败");
        }
        for (String applyNO : applyNOs) {
            LambdaQueryWrapper<UsPrintInfo> queryWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<UsPrintInfo> wrapper = queryWrapper.eq(UsPrintInfo::getApplyNo, applyNO).eq(UsPrintInfo::getPrintStatus, "未打印");
            UsPrintInfo usPrintInfo = usPrintInfoService.getOne(wrapper);
            if (usPrintInfo == null) {
                return AjaxResult.error("打印失败");
            }
            PrintUtil.PrintPdfByPath(usPrintInfo.getPrintUrl());
            PrintInfoDao printInfoDao = new PrintInfoDao();
            printInfoDao.setCheckListId(usPrintInfo.getCheckListId());
        }
        //后续需要根据返回状态判断
        return AjaxResult.success("打印成功");

    }

}
